/*
 * This file is part of Annuaire.
 *
 * Annuaire is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Foobar is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Annuaire.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.miage.annuaire.data;

import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.miage.annuaire.Membre;
import org.miage.annuaire.Structure;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * Mock de la classe XmlDataAccess.
 * @author guhumber
 */
public class XmlDataAccessMock implements XmlDataAccess {
	
	/**
	 * A implémenter.
	 */
	@Override
	public Document getAllStructures() throws ParserConfigurationException {
		return null;
	}

	@Override
	public Document getStructuresByKeys(List<String> keys)
		throws ParserConfigurationException {
		return null;
	}
	
	/**
	 * Renvoie deux membres.
	 */
	@Override
	public Document getMembres(String paramName, String paramFunction,
			String paramStructure) throws ParserConfigurationException {
		if (this.throwException) {
			throw new ParserConfigurationException("msg");
		}
		
		return this.getMembres();
	}
	
	/**
	 * Renvoie deux membres.
	 */
	@Override
	public Document getMembresByName(String name)
			throws ParserConfigurationException {
		this.getMembresByNameCallsNb++;
		this.getMembresByNameLastParam = name;
		
		if (this.throwException) {
			throw new ParserConfigurationException("msg");
		}
		
		return this.getMembres();	
	}

	/**
	 * Renvoie deux membres.
	 */
	@Override
	public Document getMembresByFunction(String function)
			throws ParserConfigurationException {
		this.getMembresByFunctionCallsNb++;
		
		if (this.throwException) {
			throw new ParserConfigurationException("msg");
		}
		
		return this.getMembres();
	}

	/**
	 * Renvoie deux membres.
	 */
	@Override
	public Document getMembresByStructure(String structure)
			throws ParserConfigurationException {
		this.getMembresByStructureCallsNb++;
		
		if (this.throwException) {
			throw new ParserConfigurationException("msg");
		}
		
		return this.getMembres();
	}
	
	/**
	 * Construit et renvoie un document XML qui contient des membres.
	 * @return Un document XML qui contient deux membres.
	 * @throws ParserConfigurationException S'il y a une erreur dans la création
	 * du document.
	 */
	private Document getMembres() throws ParserConfigurationException {
		Document document = this.createDocument();
		Element membres = document.createElement("membres");
		
		this.createMembre(document, membres, createMembre(1));
		this.createMembre(document, membres, createMembre(2));
		
		return document;
	}

	/**
	 * Crée un document XML.
	 * @return Le document XML crée.
	 * @throws ParserConfigurationException
	 */
	private Document createDocument() throws ParserConfigurationException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		return builder.newDocument();
	}
	
	/**
	 * Crée un membre dans l'élément racine 'membres'.
	 * @param document Le document XML.
	 * @param membres L'élément racine 'membres'.
	 * @param membre Le membre à ajouter.
	 */
	private void createMembre(Document document, Element membres,
			Membre membre) {
		
		Element elemMembre = document.createElement("membre");
		
		this.createTextNode(document, elemMembre, "key", membre.getKey());
		this.createTextNode(document, elemMembre, "name", membre.getName());
		this.createTextNode(document, elemMembre, "phone", membre.getPhone());
		this.createTextNode(document, elemMembre, "office", membre.getOffice());
		this.createTextNode(document, elemMembre, "function",
				membre.getFunction());
		this.createTextNode(document, elemMembre, "title", membre.getTitre());
		
		this.createTextNode(document, elemMembre, "leader",
				membre.isLeader() ? "true" : "false");
		
		this.createTextNode(document, elemMembre, "contact",
				membre.isLeader() ? "true" : "false");
		
		this.createTextNode(document, elemMembre, "assistant",
				membre.isLeader() ? "true" : "false");
		
		membres.appendChild(elemMembre);
	}
	
	/**
	 * Crée une node de texte en tant que fils d'un élément membre.
	 * @param document Le document XML.
	 * @param membre Un élément membre.
	 * @param elementName Le nom de la balise qui contient le texte.
	 * @param textValue Le texte dans la balise.
	 */
	private void createTextNode(Document document, Element membre,
			String elementName, String textValue) {
		
		// Création du fils du membre (par exemple un tag <name>...</name>.
		Element child = document.createElement(elementName);
		
		// Ajout du texte dans le fils.
		child.appendChild(document.createTextNode(textValue));
		
		// Ajout du fils en tant que fils du membre.
		membre.appendChild(child);
	}
	
	/**
	 * Crée un membre bidon avec un numéro.
	 * @param num Le numéro de membre.
	 * @return Un membre.
	 */
	private Membre createMembre(int num) {
		Membre membre = new Membre();
		membre.setKey("key" + num);
		membre.setName("name" + num);
		membre.setPhone("phone" + num);
		membre.setOffice("office" + num);
		membre.setFunction("function" + num);
		membre.setTitre("title" + num);
		membre.setLeader(false);
		membre.setAssistantLeader(false);
		membre.setContact(false);
		
		Structure s = new Structure("s" + num, "struct" + num,
				"structure" + num);
		membre.setStructure(s);
		
		return membre;
	}

	/**
	 * Accesseur en lecture sur l'attribut 'getMembresByNameCallsNb'.
	 * @return Le nombre de fois que la fonction 'getMembresByName' a été
	 * appelée.
	 */
	public int getGetMembresByNameCallsNb() {
		return this.getMembresByNameCallsNb;
	}

	/**
	 * Accesseur en lecture sur l'attribut 'getMembresByFunctionCallsNb'.
	 * @return Le nombre de fois que la fonction 'getMembresByFunction' a été
	 * appelée.
	 */
	public int getGetMembresByFunctionCallsNb() {
		return this.getMembresByFunctionCallsNb;
	}

	/**
	 * Accesseur en lecture sur l'attribut 'getMembresByStructureCallsNb'.
	 * @return Le nombre de fois que la fonction 'getMembresByStructure' a été
	 * appelée.
	 */
	public int getGetMembresByStructureCallsNb() {
		return this.getMembresByStructureCallsNb;
	}
	
	/**
	 * Accesseur en lecture sur l'attribut 'getMembresByNameLastParam'.
	 * @return Le dernier paramètre passé à la méthode
	 * 'getMembresByNameLastParam'.
	 */
	public String getGetMembresByNameLastParam() {
		return this.getMembresByNameLastParam;
	}
	
	/**
	 * Accesseur en lecture sur l'attribut 'throwException'.
	 * @param throwException Flag qui détermine si les méthodes doivent lever
	 * une exception ou non.
	 */
	public void setThrowException(boolean throwException) {
		this.throwException = throwException;
	}
	
	/**
	 * Le nombre de fois que la fonction 'getMembresByName' a été appelée.
	 */
	private int getMembresByNameCallsNb = 0;
	
	/**
	 * Le nombre de fois que la fonction 'getMembresByFunction' a été appelée.
	 */
	private int getMembresByFunctionCallsNb = 0;
	
	/**
	 * Le nombre de fois que la fonction 'getMembresByStructure' a été appelée.
	 */
	private int getMembresByStructureCallsNb = 0;
	
	/**
	 * Le dernier paramètre passé à la méthode 'getMembresByNameLastParam'.
	 */
	private String getMembresByNameLastParam = null;
	
	/**
	 * Flag qui détermine si les méthodes doivent lever une exception ou non.
	 */
	private boolean throwException = false;

    @Override
    public List<Membre> getMembresByFunctionList(String function) throws ParserConfigurationException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Document getMembresByNameWithFonction(String name, List<Membre> LaList) throws ParserConfigurationException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public List<Membre> getMembresByStructureList(String structure) throws ParserConfigurationException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public List<Membre> getMembresByNameWithFonctionList(String name, List<Membre> LaList) throws ParserConfigurationException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}
